<?php
class AdcReporterHelper extends AppHelper {

    var $controller = null;
    var $helpers = array('Html','Form','Time','Number','Paginator','Session');
    private $bands = null;
    private $tableParams = null;
    private $titleBands = array();
    private $pageBands = array();
    private $masterBands = array();
    private $externalparams = array();
    private $breaks = array();
    private $html = null;
    private $environment = null;
    private $col = null;
    private $row = null;
    private $fieldGroup = null;

    var $tags = array(
        'table' => '<table %s>%s</table>',
        'begintable' => '<table %s>',
        'endtable' => '</table>',
        'thead' => '<thead>%s</thead>',
        'tfoot' => '<tfoot>%s</tfoot>',
        'tbody' => '<tbody>%s</tbody>',
        'tbody' => '<tbody>%s</tbody>',
	'tr' => '<tr>%s</tr>',
	'th' => '<th %s>%s</th>',
	'td' => '<td %s>%s</td>',

	'div' => '<div %s>%s</div>',
	'pageseparator' => '<div class="pageseparator"></div>',
	'span' => '<span %s>%s</span>',
	'p' => '<p %s>%s</p>',

	'h1' => '<h1>%s</h1>',
	'h2' => '<h2>%s</h2>',
	'h3' => '<h3>%s</h3>',
	'h4' => '<h4>%s</h4>',

	'strong' => '<strong>%s</strong>',
        'em'=>'<em>%s</em>',
        'u'=>'<u>%s</u>',

        'a'=>'<a href="%s">%s</a>',
        'aclass'=>'<a href="%s" class="%s">%s</a>');

    var $reserved = array('WORKDATE','DATE','TIME','DATETIME','USER','EXERCICE','BAND','PARAMS','BREAKS');

    var $separators = array('+','-','*','/','%','(',')',',','<','>','=','?',':','|','&');

    var $months = array('ENERO','FEBRERO','MARZO','ABRIL','MAYO','JUNIO','JULIO','AGOSTO','SETIEMBRE','OCTUBRE','NOVIEMBRE','DICIEMBRE');
    var $week_days = array('DOMINGO','LUNES','MARTES','MIERCOLES','JUEVES','VIERNES','SABADO');

    function startup(&$controller){
        $this->controller = $controller;
    }

    /**
     * Helper reporteador
     * @param array $params parametros del reporte
     *      data => arreglo de datos relacionados
     *      table => arreglo con los parametros de las tablas
     *      params => parametros externos que pueden ser usados con PARAMS.
     *      bands => arreglo con las bandas que componen el reporte
     *          forma de uso: name => array(parametros)
     *              type=>{master | detail | header | footer}
     *              parent=>nombre_de_banda (solo para detail, header, master)
     *              data=>array() contenidos a ser mostrados [] para expreciones
     *              group=>'[]' solo para banda header y footer, permite crear agrupaciones
     *              border=>true | array() para bordes
     *              strong=>true negrita
     */
    function report($params = array(), $echo = true){
        // inicializando
        $this->bands = null;
        $this->tableParams = null;
        $this->titleBands = array();
        $this->pageBands = array();
        $this->masterBands = array();
        $this->externalparams = array();
        $this->breaks = array();
        $this->html = null;
        $this->environment = null;
        $this->col = null;
        $this->row = null;
        // inicio
        if (!array_key_exists('data', $params)) return;
        $this->data = $params['data'];

        if (!array_key_exists('bands', $params)) return;
        $this->bands = $params['bands'];

        if (array_key_exists('table', $params))
            $this->tableParams = $params['table'];
        else
            $this->tableParams = array('width'=>'100%');

        if (array_key_exists('params', $params))
            $this->externalparams = $params['params'];

        if (array_key_exists('breaks', $params))
            $this->breaks = $params['breaks'] + array('row'=>0);

        // preparando las bandas
        foreach($this->bands as $name=>$value){
            if (!array_key_exists('type', $value)) continue;
            switch($value['type']){
                case 'title':
                    $this->titleBands = $value + array('name'=>$name,'row'=>0);
                    break;
                case 'header':
                    if (!array_key_exists('parent', $value)) continue;
                    if ($value['parent']=='page'){
                        $this->pageBands['header'] = $value + array('name'=>$name,'row'=>0);
                    } else {
                        $this->assignHeader($value['parent'], $value + array('name'=>$name,'row'=>0));
                    }
                    break;
                case 'footer':
                    if (!array_key_exists('parent', $value)) continue;
                    if ($value['parent']=='page'){
                        $this->pageBands['footer'] = $value + array('name'=>$name,'row'=>0);
                    } else {
                        $this->assignFooter($value['parent'], $value + array('name'=>$name,'row'=>0));
                    }
                    break;
                case 'master':
                    $this->masterBands = $value + array('name'=>$name,'row'=>0);
                    break;
                case 'detail':
                    $this->assignDetail($value['parent'], $value + array('name'=>$name,'row'=>0));
                    break;
            }
        }

        $empty = array_key_exists('empty',$this->tableParams)?$this->tableParams['empty']:false;
        $tr = '';
        $line = '';
        // inicializando la tabla
        $params = '';
        foreach($this->tableParams as $param=>$value){
            $params .= " $param=\"{$value}\" ";
        }
        $table = sprintf($this->tags['begintable'], $params);

        // page header
        if (array_key_exists('header', $this->pageBands) && array_key_exists('data', $this->pageBands['header'])){
            $cell = $this->formatData($this->pageBands['header']['data'], $this->pageBands['header'],'td');
            $line .= sprintf($this->tags['tr'], $cell);
        }
        // titulo
        if (array_key_exists('data', $this->titleBands)){
            $cell = $this->formatData($this->titleBands['data'], $this->titleBands,'td');
            $line .= sprintf($this->tags['tr'], $cell);
        }

        $actualBand = 0;
        $band[$actualBand] = &$this->masterBands;

        // primero se procesa el MasterData header
        if (isset($band[$actualBand]['headers'])){
            $headers = $band[$actualBand]['headers'];
            foreach($headers as $n=>$header){
                if (isset($header['group'])) continue;
                $cell = $this->formatData($header['data'], $header, 'th', true);
                $line .= sprintf($this->tags['tr'], $cell);
                if (!empty($this->fieldGroup))
                    $line .= sprintf($this->tags['tr'], $this->fieldGroup);
            }
        }
        $tr = sprintf($this->tags['thead'], $line);

        if ($empty && count($this->data) == 0) {
            return '';
        }        
        $tr .= $this->processBand($this->data, $this->masterBands);

        // page footer
        if (array_key_exists('footer', $this->pageBands) && array_key_exists('data', $this->pageBands['footer'])){
            $line = $this->formatData($this->pageBands['footer']['data'], $this->pageBands['footer'],'td');
            $tr .= sprintf($this->tags['tfoot'], $line);
        }
        $table .= $tr.$this->tags['endtable'];
        $this->html = $table;

        if ($echo) echo $this->html;
        else return $this->html;
    }

    function processBand($source = null, &$band = null){
        $tr = '';
        // procesamos en encabezado
        if (isset($band['headers']) && $band['type'] != 'master'){
            $headers = &$band['headers'];
            foreach($headers as $n=>$header){
                if (isset($header['group'])) continue;
                $cell = $this->formatData($header['data'], $header, 'th', true);
                $tr .= sprintf($this->tags['tr'], $cell);
                if (!empty($this->fieldGroup))
                    $tr .= sprintf($this->tags['tr'], $this->fieldGroup);
                $tr .= $this->processBreak(); // contador de filas para posibles quiebres
            }
        }
        foreach($source as $k=>$environment){
            $groupFooters = '';
            $this->environment = $environment;

            // procesamos la fila de datos
            if (isset($band['data'])){
                $cell = $this->formatData($band['data'], $band, 'td');
                $data = sprintf($this->tags['tr'], $cell);
            }

            // procesando los grupos del master o detalle
//            $last = null;
            if (isset($band['headers'])){
                $headers = &$band['headers'];
                foreach($headers as $n=>&$header){
                    if (!isset($header['group'])) continue;
                    if (!isset($header['last']))
                        $last = null;
                    else
                        $last = $header['last'];

                    $actual = $this->parse($header['group'], $header);
//                    echo $actual .'/'.$last.'<br>';
                    if ($actual != $last){
                        // calculando primer elemento
                        $header['TOTALS'] = isset($band['VALUES'])?$band['VALUES']:array();
                        $cell = $this->formatData($header['data'], $header, 'td', true);
                        $tr .= sprintf($this->tags['tr'], $cell);
                        if (!empty($this->fieldGroup))
                            $tr .= sprintf($this->tags['tr'], $this->fieldGroup);
                        $header['row']++; // new
                        $tr .= $this->processBreak(); // contador de filas para posibles quiebres
                    } else { // totalizando
                        if (!isset($header['TOTALS']))
                            $header['TOTALS'] = $band['VALUES'];
                        else {
                            foreach($header['TOTALS'] as $key=>&$value){
                                if (isset($band['VALUES'][$key]))
                                    $quantity = $band['VALUES'][$key];
                                else
                                    $quantity = 0;
                                $value += $quantity;
                            }
                        }
                    }
                    $header['last'] = $actual;

                    // footers de grupo
                    if (isset($band['footers'])){
                        $footers = &$band['footers'];
                        $doit = false;
//                        for ($it = count($footers) - 1; $it >= 0; $it--){
//                            $footer =& $footer[$it];
                        foreach($footers as &$footer){
                            if (!isset($footer['group']) || $footer['group'] != $header['name']) continue;

                            if ($band['row'] + 1 < count($source) && isset($source[$band['row'] + 1])){
                                $temp = $this->environment;
                                $this->environment = $source[$band['row'] + 1];
                                $actual = $this->parse($header['group'], $header);
                                $this->environment = $temp;
                                $doit = $actual != $header['last'];
                            } else {
                                $doit = true;
                            }
                            if ($doit){
                                $footer['TOTALS'] = &$header['TOTALS'];
                                $cell = $this->formatData($footer['data'], $footer, 'td', false);
                                $groupFooters = sprintf($this->tags['tr'], $cell). $groupFooters;
                                $footer['row']++; // new
                                $groupFooters .= $this->processBreak(); // contador de filas para posibles quiebres
                                $band['groupFooter'] = $groupFooters;                                
                                break;
                            }
                        }
                    }
                }
            }

            // adicionando la fila de datos
            $tr .= $data;

            // hacer la llamada para los detalles
            if (isset($band['detail']) && count($band['detail'])>0){
                $temp = $environment;

                $modelsband = explode('.',$band['detail']['model']);
                $detEnvironment = $environment;
                foreach($modelsband as $m){
                    $detEnvironment = $detEnvironment[$m];
                }

                $tr .= $this->processBand($detEnvironment, $band['detail']);
                $environment = $temp;
            }

            // adicionando los pie de grupo GroupFooters
            $tr .= $groupFooters;
            $groupFooters = '';            

            $band['row']++;
            $tr .= $this->processBreak(); // contador de filas para posibles quiebres
        }
		
		// procesamos el pie de detalle
		if (/*!isset($source[$band['row']+1]) && */isset($band['footers'])){
			$footers = &$band['footers'];
			for($i = 0; $i < count($footers); $i++){
				if (isset($footers[$i]['group'])) continue;
				$cell = $this->formatData($footers[$i]['data'], $footers[$i], 'td');
				$tr .= sprintf($this->tags['tr'], $cell);
				$tr .= $this->processBreak(); // contador de filas para posibles quiebres
			}
		}
			
        return $tr;
    }

    function formatData($data = null, &$band = array(), $tag = '', $grouping = false, $debug = false){
        if (!is_array($data)) {
            $data = array($data);
        }
        $line = '';
        $i = 0;
        $fgroup = '';
        $fgcolspan = 1;
        if ($grouping) $this->fieldGroup = '';
        $gcount = 0;
        foreach ($data as $d=>$v){
            $this->col = $i;
            $params = '';
            if (is_numeric($d)) {
                $d = $v;
                $v = $band;
            } else {
                if (!is_array($v)){
                    if (is_numeric($v)){
                        $params = ' colspan="'.$v.'" ';
                    } else if (is_string($v)){
                        if ($v == 'left' || $v == 'right' || $v == 'center')
                            $params = ' align="'.$v.'" ';
                        if ($v == 'top' || $v == 'bottom' || $v == 'middle')
                            $params = ' valign="'.$v.'" ';
                    }
                    $v = $band;
                }
                foreach($band as $key=>$value){ // igualando v a band
                    if ($key!='data' && $key!='name' && $key!='TOTALS' && !array_key_exists($key, $v))
                        $v[$key] = $value;
                }
            }

            $d = $this->parse($d, $v, $debug);

            $blanker = false;
            // agrupando celdas
            if ($grouping){
                if (isset($v['grouping'])){
                    $g = $v['grouping'];
                    if($fgroup == $g) $fgcolspan++;
                    $keys = array_keys($data);

                    if (isset($keys[$i+1])){
                        if (!is_numeric($keys[$i+1]))
                            $c = isset($data[$keys[$i+1]]['grouping'])?$data[$keys[$i+1]]['grouping']:'';
                        else $c = '';

                        if ($c != $g) {
                            $g = $this->parse($g);
                            $fgroup = $g;
                        } else {
                            $fgroup = $g;
                            $g = '';
                        }
                    } else {
                        $g = $this->parse($g);
                        $fgroup = $g;
                    }
                    $gcount++;
                } else {
                    $g = '';
                }
            } else {
                $g = '';
                $fgcolspan = 1;
            }
            $g = trim($g);
            // valor por defecto
            if ((empty($d) || $d == '') && array_key_exists('default', $v)){
                $blanker = true;
                $d = $v['default'];
            }
            // obtiene la sumatoria de la banda
            $d = trim($d);
            $fd = (float)str_replace(',', '', $d)+0;

            if (is_numeric($fd) && isset($band['type']) &&
                    ($band['type'] == 'master' || $band['type'] == 'detail')){
                // almacenando valores
                if (!isset($band['VALUES'][$i]) || empty($band['VALUE'][$i])){
                    $band['VALUES'][$i] = 0;
                }
                $band['VALUES'][$i] = (float)$fd;

                // almacenando e incrementando totales
                if (!isset($band['TOTALS'][$i])){
                    $band['TOTALS'][$i] = 0;
                }
                $band['TOTALS'][$i] += (float)$fd;
            }
            
            if ($blanker) $d = '';

            $cell = $d;
            $gcell = $g;
            if (array_key_exists('em', $v)){ // italica
                $cell = sprintf($this->tags['em'], $cell);
                $gcell = !empty($gcell)?sprintf($this->tags['em'], $gcell):'';
            }

            if (array_key_exists('u', $v)){ // underline
                $cell = sprintf($this->tags['u'], $cell);
                $gcell = !empty($gcell)?sprintf($this->tags['u'], $gcell):'';
            }

            if (array_key_exists('strong', $v)){
                $cell = sprintf($this->tags['strong'], $cell);
                $gcell = !empty($gcell)?sprintf($this->tags['strong'], $gcell):'';
            }

            if (array_key_exists('header', $v)){
                $cell = sprintf($this->tags[$band['header']], $cell);
                $gcell = !empty($gcell)?sprintf($this->tags[$band['header']], $gcell):'';
            }

            // parameters
            if (array_key_exists('align', $v))
                $params .= ' align="'.$v['align'].'" ';
            if (array_key_exists('valign', $v))
                $params .= ' valign="'.$v['valign'].'" ';
            if (array_key_exists('width', $v))
                $params .= ' width="'.$v['width'].'" ';
            if (array_key_exists('height', $v))
                $params .= ' height="'.$v['height'].'" ';
            $gparams = ' align="center" valign="middle" ';

            if (array_key_exists('colspan', $v) && $v['colspan'] > 1)
                $params .= ' colspan="'.$v['colspan'].'" ';
            if (array_key_exists('rowspan', $v) && $v['rowspan'] > 1)
                $params .= ' rowspan="'.$v['rowspan'].'" ';
            if (!empty($g) && $fgcolspan > 1)
                $gparams .= ' colspan="'.$fgcolspan.'" ';

            // bordes
            if (array_key_exists('border', $v)){
                if (is_array($v['border'])){
                    $l = 'solid';
                    if (array_key_exists('line', $v['border']))
                        $l = $v['border']['line'];

                    $content = '';
                    if (array_key_exists('top', $v['border'])){
                        if (is_string($v['border']['top']))
                            $content .= 'border-top:'.$v['border']['top'].';';
                        else if ($v['border']['top'])
                            $content .= 'border-top:'.$l.' 1px black;';
                    }
                    if (array_key_exists('bottom', $v['border'])){
                        if (is_string($v['border']['bottom']))
                            $content .= 'border-bottom:'.$v['border']['bottom'].';';
                        else if ($v['border']['bottom'])
                            $content .= 'border-bottom:'.$l.' 1px black;';
                    }
                    if (array_key_exists('left', $v['border'])){
                        if (is_string($v['border']['left']))
                            $content .= 'border-left:'.$v['border']['left'].';';
                        else if ($v['border']['left'])
                            $content .= 'border-left:'.$l.' 1px black;';
                    }
                    if (array_key_exists('right', $v['border'])){
                        if (is_string($v['border']['right']))
                            $content .= 'border-right:'.$v['border']['right'].';';
                        else if ($v['border']['right'])
                            $content .= 'border-right:'.$l.' 1px black;';
                    }
                    $params.= ' style="'.$content.'" ';
                } else if (is_string($v['border'])) {
                    $params.= ' style="border:'.$v['border'].';" ';
                } else if ($v['border']) {
                    $params.= ' style="border:solid 1px black;" ';
                }
            }

            if ($tag == ''){
                $line .= sprintf($this->tags['div'], $params, $cell);
            } else {
                if (empty($fgroup)) {
                    $line .= sprintf($this->tags[$tag], $params, $cell);
                } else {
                    if ($gcount>0 && isset($v['grouping'])){
                        $this->fieldGroup .= sprintf($this->tags[$tag], $params, $cell);
                    } else {
                        $line .= sprintf($this->tags[$tag], $params, $cell);
                    }
                    if (!empty($g)){
                        $line .= sprintf($this->tags[$tag], $gparams, $gcell);
                        $fgcolspan = 1;
                    }
                }
            }
            $i++;
        }
        return $line;
    }

    function parse($data, $band = array(), $debug = false){
        $line = '';
        $var = '';
        $isLine = true;
        for ($i = 0; $i < strlen($data); $i++){
            if ($data[$i] == '['){
                $isLine = false;
            } else if ($data[$i] == ']'){
                $line .= $this->evaluate($var, $band, $this->environment, $debug);
                $var = '';
                $isLine = true;
            } else {
                if ($isLine)
                    $line .= $data[$i];
                else
                    $var .= $data[$i];
            }
        }
        return $line;
    }

    function evaluate($data, $band = array(), $environment = null, $debug = false){
        $vars = explode('.', $data);
        foreach($this->separators as $sep){ // verificando si es una expresion compuesta
            if (strpos($data, $sep) != false){
                $vars[0]='';
                break;
            }
        }

        switch ($vars[0]){
            case 'WORKDATE':
                return $this->formatValue($this->Session->read('Ejercicio.Actual.fecha'),$band);
                break;
            case 'WORKYEAR':
                $date = $this->Session->read('Ejercicio.Actual.fecha');
                $date = explode('/',$date);
                return $date[2];
                break;
            case 'WORKMONTH':
                $date = $this->Session->read('Ejercicio.Actual.fecha');
                $date = explode('/',$date);
                return $this->months[ $date[1]-1 ];
                break;
            case 'DATE':
                if (array_key_exists('format', $band))
                    $format = $band['format'];
                else if (count($vars) > 1)
                    $format = $vars[1];
                else
                    $format = 'd/m/Y';
                return $this->formatValue(date($format),$band);
                break;
            case 'TIME':
                if (array_key_exists('format', $band))
                    $format = $band['format'];
                else if (count($vars) > 1)
                    $format = $vars[1];
                else
                    $format = 'h:i a';
                return $this->formatValue(date($format),$band);
                break;
            case 'DATETIME':
                if (array_key_exists('format', $band))
                    $format = $band['format'];
                else if (count($vars) > 1)
                    $format = $vars[1];
                else
                    $format = 'd/m/Y h:i a';
                return $this->formatValue(date($format),$band);
                break;
            case 'USER':
                $param = 'Usuario';
                if (count($vars) > 1){
                    for($i = 1; $i < count($vars); $i++){
                        $param .= ".{$vars[$i]}";
                    }
                } else
                    $param .= '.usuario';
                return $this->formatValue($this->Session->read($param),$band);
                break;
            case 'EXERCICE':
                $param = 'Ejercicio';
                if (count($vars) > 1){
                    for($i = 1; $i < count($vars); $i++){
                        $param .= ".{$vars[$i]}";
                    }
                } else
                    $param .= '.codigo';
                return $this->formatValue($this->Session->read($param),$band);
                break;
            case 'BREAKS':
                $data = substr($data,strlen($vars[0])+1);
                unset($vars[0]); // elimino PARAMS
                if (!isset($this->breaks[$data])) return;
                return $this->formatValue($this->breaks[$data],$band);
                break;
            case 'PARAMS':
                $data = substr($data,strlen($vars[0])+1);
                unset($vars[0]); // elimino PARAMS
                $parts = explode('.',$data);
                if (!isset($this->externalparams[$parts[0]])) return;
                $res = $this->externalparams;
                foreach ($parts as $part){
                    $res = $res[$part];
                }
                return $this->formatValue($res, $band);
                break;
            case 'BAND':
                unset($vars[0]); // elimino BAND
                $bandName = $vars[1];
                unset($vars[1]);
                // ubicando la banda en cuestion (solo en master o detail)
                $bandfn = $this->masterBands;
                while (!empty($bandfn)){
                    if (isset($bandfn['name']) && $bandfn['name']==$bandName){
                        break;
                    } 
                    $bandres = null;
                    // buscar en los headers
                    if (isset($bandfn['headers'])){
                        foreach($bandfn['headers'] as $header){
                            if (isset($header['name']) && $header['name']==$bandName){
                                $bandres = $header;
                                break;
                            }
                        }
                    }
                    // buscar en los footers
                    if (empty($bandres) && isset($bandfn['footers'])){
                        foreach($bandfn['footers'] as $footer){
                            if (isset($footer['name']) && $footer['name']==$bandName){
                                $bandres = $footer;
                                break;
                            }
                        }
                    }
                    if (!empty($bandres)){
                        $bandfn = $bandres;
                        break;
                    }
                    if (isset($bandfn['detail'])) {
                        $bandfn = $bandfn['detail'];
                    } else if (in_array($bandfn['type'],array('master','detail'))) $bandfn = null;
                }
                if (empty($bandfn)) break;

                $follow = true;
                $result = '';
                $i = 0;

                foreach($vars as $var){
                    $follow = eval ("return array_key_exists('$var',\$bandfn{$result});");
                    if (!$follow) break;
                    $result .= "['$var']";
                    $i++;
                }

                if (!$follow) break;
                $result = eval ("return \$bandfn{$result};");
                
                return $this->formatValue($result, $band);
                break;
            default:
                $data = str_replace(' ', '', $data);
                $tokens = array();
                $item = '';
                // separando la expresion en tokens
                for($i = 0; $i < strlen($data); $i++){
                    if (in_array($data[$i], $this->separators)){
                        if ($item != '')
                            $tokens = array_merge($tokens,array($item));
                        $tokens = array_merge($tokens,array($data[$i]));
                        $item = '';
                    } else {
                        $item .= $data[$i];
                    }
                }
                if (strlen($item)>0)
                    $tokens = array_merge($tokens,array($item));
                // sustituyendo los tokens relacionados con el modelo de entorno
                // y obteniendo la expresion a evaluar
                $statement = '';
                foreach ($tokens as $token){
                    $env = $environment;
                    if (!in_array($token, $this->separators)){
                        $vars = explode('.', $token);
                        // palabras claves
                        if (in_array($vars[0],$this->reserved)){
                            $token = "'".$this->evaluate($token, $band, $env)."'";
                        } else { // evalua valores
                            if (count($vars) == 0 || empty($env)) continue;
                            $found = array_key_exists($vars[0], $env);
                            if ($found) {
                                $env = $env[$vars[0]];
                                unset($vars[0]);
                            }
                            foreach($vars as $var){
                                if (array_key_exists($var, $env)){
                                    $env = $env[$var];
                                    $found = true;
                                } else {
                                    $found = false;
                                    break;
                                }
                            }
                            if ($found){
                                $tempband = $band;
                                $token = "'".$env."'";

                            } else if (count($vars)>1)
                                $token = '\'-\'';
                        }
                    }
                    $statement .= $this->str_special_escape($token);
                }

//                echo '['.$statement.']<br>';
//                $debug = Configure::read('debug');
                $result = '';
//                Configure::write('debug',0);
                if (!empty($statement) && trim($statement) != '')
                    $result = eval ("return $statement;");
                else
                    $result = '';
//                Configure::write('debug',$debug);

                return $this->formatValue($result, $band);
                break;
        }
    }

    function formatValue($value, $band = array()){

        if (array_key_exists('datatype', $band)){
            if (empty($value)||$value == '')
                $band['datatype'] = 'string';
            switch ($band['datatype']){
                case 'date':
                    if (array_key_exists('format', $band))
                        $format = $band['format'];
                    else
                        $format = 'd/m/Y';
                    return $this->Time->format($format,$value);
                    break;
                case 'time':
                    if (array_key_exists('format', $band))
                        $format = $band['format'];
                    else
                        $format = 'h:i a';
                    return $this->Time->format($format,$value);
                    break;
                case 'datetime':
                    if (array_key_exists('format', $band))
                        $format = $band['format'];
                    else
                        $format = 'd/m/Y h:i a';
                    return $this->Time->format($format,$value);
                    break;
                case 'integer':
                    if (is_numeric($value)){
                        return round($value, 0);
//                        break;
                    }
                    break;
                case 'float':
                    if (is_numeric($value)){
                        return number_format($value,2,'.',',');
//                        break;
                    }
                    break;
                case 'float2':
                    if (is_numeric($value)){
                        return number_format($value,2,'.',',');
//                        break;
                    }
                    break;
                case 'float3':
                    if (is_numeric($value)){
                        return number_format($value,3,'.',',');
//                        break;
                    }
                    break;
                case 'float4':
                    if (is_numeric($value)){
                        return number_format($value,4,'.',',');
//                        break;
                    }
                    break;
                case 'boolean':
                    return ($value?'SI':'NO');
                    break;
                default:
                    return $value;
                    break;
            }
        } else { // deteccion automatica del tipo de dato
            if ($this->is_date($value))
                return $this->Time->format('d/m/Y',$value);
            else if (is_int($value))
                return round($value, 0);
            else if (is_float($value)||is_double($value))
                return number_format($value,2,'.',',');
            else if (is_bool($value))
                return ($value?'SI':'NO');
            else return $value;
        }
    }

    function processBreak($band = array()){
        $line = '';
        $tr = '';
        if (isset($this->breaks['rows']) &&
                $this->row % $this->breaks['rows'] == 0){
            if ($this->row == 0 && (!isset($this->breaks['first']) || !$this->breaks['first'])){
                $this->breaks['row']++;
                $this->row++;
                return false;
            }
            if ($this->row > 0) {
                // colocando el break footer
                if (isset($this->breaks['footer'])){
                    $cell = $this->formatData($this->breaks['footer'], $band, 'td');
                    $line .= sprintf($this->tags['tr'], $cell);
                }

                // cerrando la tabla
                $line .= sprintf($this->tags['endtable']);

                // colocando separador
                $line .= sprintf($this->tags['pageseparator']);

                // inicializando la tabla
                $params = '';
                foreach($this->tableParams as $param=>$value){
                    $params .= " $param=\"{$value}\" ";
                }
                $line .= sprintf($this->tags['begintable'], $params);

                // colocando la cabecera de pagina
                if (array_key_exists('header', $this->pageBands) && array_key_exists('data', $this->pageBands['header'])){
                    $cell = $this->formatData($this->pageBands['header']['data'], $this->pageBands['header'],'td');
                    $tr .= sprintf($this->tags['tr'], $cell);
                }

                // colocando el titulo
                if (array_key_exists('data', $this->titleBands)){
                    $cell = $this->formatData($this->titleBands['data'], $this->titleBands,'td');
                    $tr .= sprintf($this->tags['tr'], $cell);
                }

                // colocando la cabecera de master
                if (array_key_exists('headers', $this->masterBands)){
                    $headers = $this->masterBands['headers'];
                    foreach($headers as $n=>$header){
                        if (array_key_exists('group', $header)) continue;
                        $cell = $this->formatData($header['data'], $header, 'th', true);
                        $tr .= sprintf($this->tags['tr'], $cell);
                        if (!empty($this->fieldGroup))
                            $tr .= sprintf($this->tags['tr'], $this->fieldGroup);
                    }
                }
                $line .= sprintf($this->tags['thead'], $tr);
            }
            // colocando el break header
            if (isset($this->breaks['header'])){
                $cell = $this->formatData($this->breaks['header'], $band, 'td');
                $line .= sprintf($this->tags['tr'], $cell);
            }
            $this->breaks['row']++;
            $this->row++;
            return $line;
        } else {
            $this->row++;
            return false;
        }
    }

    function assignHeader($name = null, $item = array()){
        $i = 0;
        $band[$i] = &$this->masterBands;
        $follow = true;
        do {
            $follow = array_key_exists($i, $band);
            if ($follow && $band[$i]['name']==$name){
                if (array_key_exists('headers', $band[$i]))
                    array_push($band[$i]['headers'], $item);
                else
                    $band[$i]['headers'][0] = $item;
            }

            if ($follow && array_key_exists('detail', $band[$i])){
                if ($follow)
                    $band[$i+1] = &$band[$i]['detail'];
            } else $follow = false;
            $i++;
        } while($follow);
    }

    function assignFooter($name = null, $item = array()){
        $i = 0;
        $band[$i] = &$this->masterBands;
        $follow = true;
        do {
            $follow = array_key_exists($i, $band);
            if ($follow && $band[$i]['name']==$name){
                if (array_key_exists('footers', $band[$i]))
                    array_push($band[$i]['footers'], $item);
                else
                    $band[$i]['footers'][0] = $item;
            }

            if ($follow && array_key_exists('detail', $band[$i])){
                if ($follow)
                    $band[$i+1] = &$band[$i]['detail'];
            } else $follow = false;
            $i++;
        } while($follow);
    }

    function assignDetail($name = null, $item = array()){
        $i = 0;
        $band[$i] = &$this->masterBands;
        do {
            if ($band[$i]['name']==$name){
//                if (array_key_exists('detail', $band[$i]))
                    $band[$i]['detail'] = $item;
//                else
//                    $band[$i]['detail'] = $item;
            }

            if (array_key_exists('detail', $band[$i])){
                $band[$i+1] = &$band[$i]['detail'];
            }
            $i++;
        } while(array_key_exists('detail', $band));
    }

    function restaFechas($dFecIni, $dFecFin){
        $dFecIni = str_replace('-','',$dFecIni);
        $dFecIni = str_replace('/','',$dFecIni);
        $dFecFin = str_replace('-','',$dFecFin);
        $dFecFin = str_replace('/','',$dFecFin);

        ereg( '([0-9]{1,2})([0-9]{1,2})([0-9]{2,4})', $dFecIni, $aFecIni);
        ereg( '([0-9]{1,2})([0-9]{1,2})([0-9]{2,4})', $dFecFin, $aFecFin);

        $date1 = mktime(0,0,0,$aFecIni[2], $aFecIni[1], $aFecIni[3]);
        $date2 = mktime(0,0,0,$aFecFin[2], $aFecFin[1], $aFecFin[3]);

        return round(($date2 - $date1) / (60 * 60 * 24));
    }

    function is_date($fecha){
        //Comprueba si la cadena introducida es de la forma D/m/Y (15/04/1920)
        if (ereg("([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})", $fecha, $bloques)){
            return checkdate($bloques[2], $bloques[3], $bloques[1]);
        } else if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $fecha, $bloques)){
            return checkdate($bloques[2], $bloques[3], $bloques[1]);
        } else return false;
        return true;
    }

    function str_special_escape($str){
        if($str[0] == '\'' && $str[strlen($str)-1] == '\'' && count(explode('\'',$str)) > 3){
            $res = $str[0];
            for ($i = 1; $i < strlen($str) - 1; $i++){
                if ($str[$i] == '\'')
                    $res .= '\\\'';
                else
                    $res .= $str[$i];
            }
            $res .= $str[strlen($str)-1];
            $str = $res;
        }
        return $str;
    }

    function get_week_day($date){
        if (!strpos($date,'/'))
            list($y,$m,$d) = explode('-',$date);
        else
            list($y,$m,$d) = explode('/',$date);
        $w = date('w', mktime(0,0,0,$m,$d,$y));
        return $this->week_days[$w];
    }

}
?>